package com.isoft.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig implements CommandLineRunner {

    private static final Logger logger = LoggerFactory.getLogger(RedisConfig.class);

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);

        // 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(mapper);

        // 使用StringRedisSerializer来序列化和反序列化redis的key值
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();

        return template;
    }

    @Override
    public void run(String... args) throws Exception {
        // 应用启动时检查Redis连接
        checkRedisConnection();
    }

    /**
     * 检查Redis连接状态
     */
    public void checkRedisConnection() {
        try {
            RedisTemplate<String, Object> redisTemplate = redisTemplate(null);
            String testKey = "redis_connection_test";
            String testValue = "test_" + System.currentTimeMillis();
            
            // 测试写入
            redisTemplate.opsForValue().set(testKey, testValue, 10, java.util.concurrent.TimeUnit.SECONDS);
            
            // 测试读取
            Object result = redisTemplate.opsForValue().get(testKey);
            
            if (testValue.equals(result)) {
                logger.info("✅ Redis连接成功！");
                logger.info("Redis服务器信息: {}", redisTemplate.getConnectionFactory().getConnection().info());
            } else {
                logger.error("❌ Redis连接测试失败：读写不一致");
            }
            
            // 清理测试数据
            redisTemplate.delete(testKey);
            
        } catch (Exception e) {
            logger.error("❌ Redis连接失败: {}", e.getMessage());
            logger.error("请检查Redis服务是否启动，以及配置是否正确");
            logger.error("Redis配置检查清单:");
            logger.error("1. Redis服务是否启动 (redis-server)");
            logger.error("2. Redis端口是否为6379");
            logger.error("3. Redis是否需要密码认证");
            logger.error("4. 防火墙是否阻止连接");
            
            // 在开发环境中，可以选择继续启动应用
            // 在生产环境中，可能需要阻止应用启动
            logger.warn("⚠️ 应用将继续启动，但验证码功能可能不可用");
        }
    }
} 